package mk.jug.academy.service;

import java.util.List;
import java.util.logging.Logger;

import javax.persistence.NoResultException;

import mk.jug.academy.dao.StudentDAO;
import mk.jug.academy.exception.BusinessException;
import mk.jug.academy.model.Page;
import mk.jug.academy.model.Student;
import mk.jug.academy.model.status.StudentStatus;
import mk.jug.academy.preconditions.ErrorCodes;
import mk.jug.academy.preconditions.PreconditionExceptions;
import mk.jug.academy.preconditions.StudentPreconditions;
import mk.jug.academy.util.Utils;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;


/**
 * Provides the business logic for {@link StudentService}.
 * 
 * @author Ice.Penov
 */
@Service
public class StudentServiceImpl implements StudentService {

	@Autowired private StudentDAO studentDAO;
	
	private static Logger LOG = Logger.getLogger(StudentServiceImpl.class.getName());
	
	@Override
	public void registerStudent(Student student) {
		StudentPreconditions.registerStudent(student);
		if (!exists(student.getEmail())) {			
			student.setStatus(StudentStatus.SIGNED_UP);
			studentDAO.save(student);
			LOG.info("New student has been registered [" + student.getCode() + "]");
		} else {
			throw new BusinessException(ErrorCodes.ERROR_EMAIL_EXISTS);
		}
	}	
	
	@Override
	public Page<Student> listAll(int pageNumber, int itemsPerPage) {
		return studentDAO.findAll(Utils.calculateStart(pageNumber, itemsPerPage), itemsPerPage);
	}

	@Override
	public void approveRegistration(Student student) {		
		StudentPreconditions.approveRegistration(student);
		student.setStatus(StudentStatus.WAITING_FOR_ENROLLMENT);
		studentDAO.save(student);
	}

	@Override
	public Page<Student> listSignedUp(int pageNumber, int itemsPerPage) {
		return studentDAO.findByStatus(StudentStatus.SIGNED_UP, Utils.calculateStart(pageNumber, itemsPerPage), itemsPerPage);
	}

	@Override
	public Page<Student> listWaitingForEnrollment(int pageNumber, int itemsPerPage) {
		return studentDAO.findByStatus(StudentStatus.WAITING_FOR_ENROLLMENT, Utils.calculateStart(pageNumber, itemsPerPage), itemsPerPage);
	}

	@Override
	public Page<Student> listEnrolled(int pageNumber, int itemsPerPage) {
		return studentDAO.findByStatus(StudentStatus.ENROLLED, Utils.calculateStart(pageNumber, itemsPerPage), itemsPerPage);
	}

	@Override
	public Page<Student> listRejected(int pageNumber, int itemsPerPage) {
		return studentDAO.findByStatus(StudentStatus.REJECTED, Utils.calculateStart(pageNumber, itemsPerPage), itemsPerPage);
	}
	
	@Override
	public List<Student> fetchWaiting() {
		return studentDAO.findByStatus(StudentStatus.WAITING_FOR_ENROLLMENT);
	}

	@Override
	public void denyRegistration(Student student) {
		StudentPreconditions.denyRegistration(student);
		student.setStatus(StudentStatus.REJECTED);
		studentDAO.save(student);
	}
		
	@Override
	public Student load(Long id) {
		return studentDAO.find(Student.class, id);
	}
	
	@Override
	public void saveChanges(Student student) {
		Assert.notNull(student.getId(), PreconditionExceptions.ID_IS_NULL);
		studentDAO.save(student);
		LOG.info("Student has been modified [" + student.getCode() + "]");
	}
	
	@Override
	public boolean exists(String email) {
		try {			
			studentDAO.findAnyByEmail(email);
		} catch (NoResultException e) {
			return false;
		}
		return true;
	}
	
	@Override
	public Student findByEmail(String email) {
		Student student = null;
		try {
			student = studentDAO.findActiveByEmail(email);
		} catch (NoResultException e) {
			;
		}
		return student;
	}
	
}